home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / langs / dl_exsrc.zoo / wildcard.c < prev   
Encoding:
C/C++ Source or Header  |  1994-07-03  |  2.7 KB  |  121 lines

  1. #include <stdlib.h>
  2. #include <regexp.h>
  3. #include <limits.h>
  4. #include <dirent.h>
  5. #include "extras.h"
  6.  
  7. /*
  8. char *wildcard(char *pathname)
  9.     Return matches for a wildcard filename.  If <pathname> is not
  10.     NULL, the first file which matches <pathname> will be returned.
  11.     The <pathname> may contain wildcards only in the filename portion,
  12.     not in any sub-directories.  Subsequent calls to wildcard() with
  13.     a NULL argument return the next matching filename.  NULL is
  14.     returned when no more files match.  Note: the pointer returned
  15.     points to an internal buffer which is overwritten with each
  16.     call.  It should not be modified, and should be copied into a
  17.     safe place if you want to save the value.
  18. */
  19.  
  20. static DIR *handle = NULL;
  21. static regexp *match = NULL;
  22.  
  23. static void release_handle()
  24. {
  25.   if (handle)
  26.     closedir(handle);
  27.   if (match)
  28.     free(match);
  29. }
  30.  
  31. char *wildcard(pathname)
  32.   const char *pathname;
  33. {
  34.   static int first_time = 1;
  35.   static char pathbuf[PATH_MAX];
  36.   static char pattern[2 * NAME_MAX];
  37.   static char *s;
  38.   register char *t, *u;
  39.   struct dirent *D;
  40.  
  41.   /* Clean up behind ourselves */
  42.   if (first_time) {
  43.     first_time = 0;
  44.     atexit(release_handle);
  45.   }
  46.  
  47.   if (pathname) {
  48.     /* Shut down the previous wildcard search, if any, and set up for a
  49.        new one. */
  50.     if (handle) {
  51.       closedir(handle);
  52.       handle = NULL;
  53.     }
  54.     if (match) {
  55.       free(match);
  56.       match = NULL;
  57.     }
  58.     t = strrpbrk(pathname, "/\\");
  59.     if (!t) {
  60.       strcpy(pathbuf, "./");
  61.       s = pathbuf + 2;
  62.       t = pathname;
  63.     } else {
  64.       t++;
  65.       strncpy(pathbuf, pathname, (int)(t - pathname));
  66.       s = pathbuf + (t - pathname);
  67.     }
  68.  
  69.     handle = opendir(pathbuf);
  70.     if (!handle)
  71.       return NULL;
  72.  
  73.     /* Translate the filename component from a DOS-style wildcard
  74.        expression to a regular expression for regexp(). */
  75.     u = pattern;
  76.     *u++ = '^';
  77.     for (; *t; t++) {
  78.       switch (*t) {
  79.     case '*':
  80.       *u++ = '.';
  81.       *u++ = '*';
  82.       break;
  83.     case '?':
  84.       *u++ = '.';
  85.       break;
  86.     case '.':
  87.       *u++ = '\\';
  88.       *u++ = '.';
  89.       break;
  90.     default:
  91.       *u++ = *t;
  92.       }
  93.     }
  94.     *u++ = '$';
  95.     *u = '\0';
  96.     match = regcomp(pattern);
  97.     if (!match) {
  98.       closedir(handle);
  99.       handle = NULL;
  100.       return NULL;
  101.     }
  102.   }
  103.  
  104.   /* Now try to read a filename from the directory, and match it with
  105.      the regular expression. */
  106.   for (;;) {
  107.     D = readdir(handle);
  108.     if (!D) {    /* end of directory */
  109.       closedir(handle);
  110.       handle = NULL;
  111.       free(match);
  112.       match = NULL;
  113.       return NULL;
  114.     }
  115.     if (regexec(match, D->d_name, 1) == 0)
  116.       continue;
  117.     strcpy(s, D->d_name);
  118.     return pathbuf;
  119.   }
  120. }
  121.